//
//  BBTestAppView.m
//  BBTUIOTest
//
//  Created by ben smith on 8/20/08.
//  This file is part of BBTUIOTest.
//
//  BBTUIOTest is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.

//  BBTUIOTest is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.

//  You should have received a copy of the GNU Lesser General Public License
//  along with BBTUIOTest.  If not, see <http://www.gnu.org/licenses/>.
// 
//  Copyright 2008 Ben Britten Smith ben@benbritten.com .
//
//


#import "BBTestAppView.h"
#import "BBTUIOCursor.h"
#import "BBScreenSelectionView.h"
#import "BBEscapeWindow.h"

@implementation BBTestAppView

@synthesize backgroundGradient;
@synthesize cursors;
@synthesize oldWindow;

-(void)awakeFromNib
{
	// set up my pretty background
	[self setupBackgroundGradient];	
	[self setup];
}

-(void)setup
{
	
}

- (id) init
{
	self = [super init];
	if (self != nil) {
		// will call this here as well, although generally we wake from nib
		[self setupBackgroundGradient];
			[self setup];
	}
	return self;
}


// all this key/first responder junk is simply so that i can get a keydown event when I
// am fullscreen

- (BOOL)canBecomeKeyView
{
	return YES;	
}

- (BOOL)acceptsFirstResponder
{
	return YES;	
}

- (BOOL)becomeFirstResponder
{
	return YES;
}

- (BOOL)resignFirstResponder
{
	return YES;
}

// this tells us that stuff has probably changed and we should 
// update the view
-(void)blobCycleDone
{
	// do the thing
	[self setNeedsDisplay:YES];
}

// the magic happens here
- (void)drawRect:(NSRect)rect 
{
	// draw the pretty gradient
	[self.backgroundGradient drawInRect:self.bounds angle:90.0];
		
	// draw the blobs
	[self drawBlobs];
	
	//draw our label
	[self drawText:@"TUIO Test View" centeredAtPoint:NSMakePoint(NSMidX([self bounds]), 10)];
}

// draw each blob
-(void)drawBlobs
{
	for (BBTUIOCursor * cursor in cursors) {
		[self drawBlobEvent:cursor];
	}
}

// draw a single blob
-(void)drawBlobEvent:(BBTUIOCursor*)cursor
{
	
	// need to scale the 0..1 style TUIO coordinates to our bounds
	float scaleX = NSWidth([self bounds]);
	float scaleY = NSHeight([self bounds]);

	NSPoint bLoc = [cursor position];
	
	// flip the y, it is from the top down in TUIO parlance,
	// but our views are bottom up
	bLoc.y = 1.0 - bLoc.y;
	
	bLoc.x *= scaleX;
	bLoc.y *= scaleY;

	// make a pretty little circle/rectangle/crosshair with label
	// thing for this blob
	// this is how big they will be
	float radius = 20;

	NSRect blobRect = NSMakeRect(bLoc.x - radius, bLoc.y - radius, radius * 2.0, radius * 2.0);
	// make a pretty oval in a rectangle. oooh!
	[[NSColor greenColor] set];
	[NSBezierPath strokeRect:blobRect];
	[[NSColor redColor] set];
	[[NSBezierPath bezierPathWithOvalInRect:blobRect] stroke];
	// now draw a cross hair, because, why not?
	[[NSColor whiteColor] set];
	[NSBezierPath strokeLineFromPoint:NSMakePoint(bLoc.x, bLoc.y - radius * 2.5) toPoint:NSMakePoint(bLoc.x, bLoc.y + radius * 2.5)];
	[NSBezierPath strokeLineFromPoint:NSMakePoint(bLoc.x - radius * 2.5,bLoc.y) toPoint:NSMakePoint(bLoc.x + radius * 2.5,bLoc.y)];
	// how bout a pretty label? definitely
	[self drawText:[NSString stringWithFormat:@"Blob %d",[cursor cursorID]] centeredAtPoint:NSMakePoint(bLoc.x, bLoc.y + radius + 12)];
}


-(void)drawText:(NSString*)text centeredAtPoint:(NSPoint)p;
{
	// the first time we want to generate the attributes 
	if (attrsDictionary == nil ) {
		NSMutableParagraphStyle * style = [[NSMutableParagraphStyle alloc] init];
		[style setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
		[style setAlignment:NSCenterTextAlignment];
		attrsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont messageFontOfSize:15],NSFontAttributeName,[NSColor greenColor],NSForegroundColorAttributeName,style,NSParagraphStyleAttributeName,nil];
		[attrsDictionary retain];
		[style release];
	}
	
	// make a storage string
	NSAttributedString * newString = [[NSAttributedString alloc] initWithString:text attributes:attrsDictionary];

	//get it's size
	NSSize ssize = [newString size];
	
	// now draw a little rectangle behind it
	[[NSColor colorWithDeviceWhite:0.0 alpha:0.3] set]; 
	NSRect backing = NSMakeRect(p.x - (ssize.width/2.0) - 5, p.y - (ssize.height/2.0) - 2, ssize.width + 10, ssize.height + 4);
	[NSBezierPath fillRect:backing];
	
	// now draw the text on top
	[newString drawAtPoint:NSMakePoint(p.x - (ssize.width/2.0), p.y - (ssize.height/2.0))];
	
	// clean up
	[newString release];	
}


- (void)setupBackgroundGradient
{
	// create a basic gradient for the background of the view
	// black
	CGFloat red1   =    0.0 / 255.0;
	CGFloat green1 =   0.0 / 255.0;
	CGFloat blue1  =  0.0 / 255.0;
	// dark sorta ocean greenie/bluie
	CGFloat red2    =  30.0 / 255.0;
	CGFloat green2  =  50.0 / 255.0;
	CGFloat blue2   =  50.0 / 255.0;
	
	NSColor* gradientTop    = [NSColor colorWithCalibratedRed:red1 green:green1 blue:blue1 alpha:1.0];    
	NSColor* gradientBottom = [NSColor colorWithCalibratedRed:red2 green:green2 blue:blue2 alpha:1.0];
	
	NSGradient* gradient;
	gradient = [[NSGradient alloc] initWithStartingColor:gradientBottom endingColor:gradientTop];
	
	self.backgroundGradient = gradient;
	[gradient release];
}

// this is a fun one.  we are going to make a new window
// and put ourselves into it (taking ourselves out of the old window)
-(IBAction)goFullScreen:(id)sender;
{
	int windowLevel;
	
	// get the screen that we want to go to
	NSScreen * chosenScreen = [screenSelector chosenScreen];
		
	// get the screen id from the screen description, and capture that display
  CGDirectDisplayID displayID = [[[chosenScreen deviceDescription] objectForKey:@"NSScreenNumber"] intValue];

	if (CGDisplayCapture( displayID ) != kCGErrorSuccess) {
		NSLog( @"Couldn't capture the display!" );
	}
	
	// Get the shielding window level
	windowLevel = CGShieldingWindowLevel();
	
	// Get the screen rect of our main display
	NSRect screenRect = [chosenScreen frame];
	
	// Put up a new window
	fullScreenWindow = [[BBEscapeWindow alloc] initWithContentRect:screenRect
																								 styleMask:NSBorderlessWindowMask
																									 backing:NSBackingStoreBuffered
																										 defer:NO
																										screen:chosenScreen];
	// put this window above the shielding window
	[fullScreenWindow setLevel:windowLevel];
	[fullScreenWindow setFrame:screenRect display:YES]; // do this twice for some reason, otherwise you sometimes get the wrong screen rect
	[fullScreenWindow setBackgroundColor:[NSColor blackColor]];
	[fullScreenWindow makeKeyAndOrderFront:nil];

	//remember the old settings before i move out
	self.oldWindow = [self window];
	oldFrame = [self frame];
	
	[self removeFromSuperview];

	// set my new frame size and insert myself into the new fullscreen window
	[self setFrame:screenRect];
	[fullScreenWindow setContentView:self];
	[fullScreenWindow makeFirstResponder:self];
	[self setNeedsDisplay:YES];
	
	// now do some hocus pocus on the old window to squeeze it down
	// because taking myself out left a big hole
	oldWindowFrame = [self.oldWindow frame];
	NSRect squished = oldWindowFrame;
	squished.size.height -= NSHeight(oldFrame);
	squished.origin.y += NSHeight(oldFrame);
	[[self.oldWindow animator] setFrame:squished display:YES];
	
	// now repurpose our GUI button to cancel the fulscreen
	[fullScreenButton setTitle:@"Stop Fullscreen"];
	[fullScreenButton setAction:@selector(closeFullScreenWindow:)];
}

// reverse the fullscreen process
-(IBAction)closeFullScreenWindow:(id)sender;
{
	// dont do nuthin if we dont have a fullscreen window
	if (fullScreenWindow == nil) return;
	
	// destroy the fullscreen window
	[fullScreenWindow orderOut:self];
	[fullScreenWindow release];
	
	if (CGReleaseAllDisplays() != kCGErrorSuccess) {
		// need to make this a bit more friendly
		NSLog( @"Couldn't release the display(s)!" );
	}
	
	// re-expand my old window to its original size
	[[self.oldWindow animator] setFrame:oldWindowFrame display:YES];

	// add myself back into the content view
	[[self.oldWindow contentView] addSubview:self];
	[self setFrame:oldFrame];
	// reset the button back to it's original use
	[fullScreenButton setTitle:@"Go Fullscreen"];
	[fullScreenButton setAction:@selector(goFullScreen:)];
}

// handle the esc key, this will close the fullscreen window
-(IBAction)keyDown:(NSEvent*)theEvent
{
	// this is the ESC key
	if ([theEvent keyCode] == 53) { 
		[self closeFullScreenWindow:self];
		return;		
	}
	
	[super keyDown:theEvent];
}

- (void) dealloc
{
	[attrsDictionary release];
	[backgroundGradient release];
	[fullScreenWindow release];
	[oldWindow release];
	
	[super dealloc];
}


@end
